#include "RenderMiscs.h"
#include "RenderResource.h"

#ifdef MFC_ENABLED
#include "DecoDirectoryManager.h"
#endif


DecoRenderMisc* DecoRenderMisc::msRenderMisc = NULL;


DecoRenderMisc* DecoRenderMisc::GetSingleton()
{
	if (!msRenderMisc)
		msRenderMisc = new DecoRenderMisc();
	return msRenderMisc;
}

void DecoRenderMisc::DestroySingleton()
{
	if (msRenderMisc)
		delete msRenderMisc;
}


void DecoRenderMisc::DrawAxis (DecoSceneNode* SN, Coords coord, BOOL bDrawX, BOOL bDrawY, BOOL bDrawZ)
{
	if (m_bHideAxis) return;
	assert(RI);
	matrix44 localToWorld;
	localToWorld.identity();
	vector3 pos = coord.origin();
	localToWorld.col[3] = vector4(pos.x, pos.y, pos.z, 1.f);
	DecoLight *Lights[MAX_LIGHT];
	INT numEffectiveLights = 0;
	if (bDrawX)
	{
		SN->GetRelevantLights(&m_axis_x, numEffectiveLights, Lights);

		m_axis_x.SetLocalToWorld(localToWorld);
		m_axis_x.Render(RI, Lights, numEffectiveLights);
	}

	if (bDrawY)
	{
		SN->GetRelevantLights(&m_axis_y, numEffectiveLights, Lights);

		m_axis_y.SetLocalToWorld(localToWorld);
		m_axis_y.Render(RI, Lights, numEffectiveLights);
	}

	if (bDrawZ)
	{
		SN->GetRelevantLights(&m_axis_z, numEffectiveLights, Lights);

		m_axis_z.SetLocalToWorld(localToWorld);
		m_axis_z.Render(RI, Lights, numEffectiveLights);
	}
}

void DecoRenderMisc::DrawBox (DecoSceneNode* SN, const Box& box, const DecoColor& color)
{
	if (m_bHideBox) return;
	assert(RI);
	DecoVertexBuffer vb;
	
	vector3 *vertices = new vector3[24];
	DecoColor *colors = new DecoColor[24];

	vector3 boxVertex[NUM_VERTICES_IN_BOX];
	box.AllVerteices(boxVertex);

	for (INT i = 0; i < NUM_VERTICES_IN_BOX * 3; ++i)
	{
		colors[i] = color;
	}
	for (INT i = 0; i < NUM_VERTICES_IN_BOX / 2; ++i)
	{
		vertices[i * 2] = boxVertex[i % 4];
		vertices[i * 2 + 1] = boxVertex[(i + 1) % 4];
		vertices[i * 2 + 8] = boxVertex[i % 4 + 4];
		vertices[i * 2 + 8 + 1] = boxVertex[(i + 1) % 4 + 4];
		vertices[i * 2 + 16] = boxVertex[i % 4];
		vertices[i * 2 + 16 + 1] = boxVertex[i % 4 + 4];


	}
	RI->ResetLight();
	RI->SetLineWidth(1);
	vb.SetVertexInformation(24, vertices, NULL, NULL, colors);
	RI->DrawPrimitive(PT_LineList, 12, DT_WireFrame, &vb);
	delete[] vertices;
	delete[] colors;
}

void DecoRenderMisc::DrawPointList(DecoSceneNode* SN, const vector3* point, UINT numPoints, const DecoColor& color, FLOAT width)
{
	DecoVertexBuffer vb;

	vector3 *vertices = new vector3[numPoints];
	DecoColor *colors = new DecoColor[numPoints];

	for (UINT i = 0; i < numPoints; i++)
	{
		vertices[i] = point[i];
		colors[i] = color;
	}
	RI->SetLineWidth(width);
	RI->ResetLight();
	vb.SetVertexInformation(numPoints, vertices, NULL, NULL, colors);
	RI->DrawPrimitive(PT_PointList, numPoints, DT_WireFrame, &vb);
	delete[] vertices;
	delete[] colors;

}

void DecoRenderMisc::DrawPointList(DecoSceneNode* SN, const vector3* point, const DecoColor* color, UINT numPoints, FLOAT width)
{
	DecoVertexBuffer vb;

	vector3 *vertices = new vector3[numPoints];
	DecoColor *colors = new DecoColor[numPoints];

	for (UINT i = 0; i < numPoints; i++)
	{
		vertices[i] = point[i];
		colors[i] = color[i];
	}
	RI->SetLineWidth(width);
	RI->ResetLight();
	vb.SetVertexInformation(numPoints, vertices, NULL, NULL, colors);
	RI->DrawPrimitive(PT_PointList, numPoints, DT_WireFrame, &vb);
	delete[] vertices;
	delete[] colors;

}

void DecoRenderMisc::DrawLine(const vector3& start, const vector3& end, DecoColor color, FLOAT width)
{
	assert(RI);
	DecoVertexBuffer vb;
	vector3 *vertices = new vector3[2];
	DecoColor *colors = new DecoColor[2];

	vertices[0] = start;
	vertices[1] = end;
	colors[0] = colors[1] = color;
	vb.SetVertexInformation(2, vertices, NULL, NULL, colors);
	RI->ResetLight();
	RI->SetLineWidth(width);
	RI->DrawPrimitive(PT_LineList, 1, DT_WireFrame, &vb);
	RI->SetLineWidth(1); // set default width
	delete[] vertices;
	delete[] colors;
}

void DecoRenderMisc::DrawLineStrip(const vector3* point, const DecoColor* color, UINT numPoints, FLOAT width)
{
	DecoVertexBuffer vb;

	vector3 *vertices = new vector3[numPoints];
	DecoColor *colors = new DecoColor[numPoints];

	for (UINT i = 0; i < numPoints; i++)
	{
		vertices[i] = point[i];
		colors[i] = color[i];
	}
	RI->SetLineWidth(width);
	RI->ResetLight();
	vb.SetVertexInformation(numPoints, vertices, NULL, NULL, colors);
	RI->DrawPrimitive(PT_LineStrip, numPoints - 1, DT_WireFrame, &vb);
	delete[] vertices;
	delete[] colors;
}


void DecoRenderMisc::DrawRotation(DecoSceneNode* SN, Coords coord, BOOL bDrawX, BOOL bDrawY, BOOL bDrawZ)
{ 
	if (m_bHideRotation) return;

	DecoLight *Lights[MAX_LIGHT];
	INT numEffectiveLights = 0;
	assert(RI);
	SN->GetRelevantLights(&m_rotation, numEffectiveLights, Lights);
	m_rotation.SetLocalToWorld(coord.GetMatrix());
	m_rotation.Render(RI, Lights, numEffectiveLights);
}



void DecoRenderMisc::Initialize(DecoRenderInterface* _RI)
{
	using namespace std;
	assert(_RI);
	//assert(!m_renderMisc);

	DecoRenderMisc* m_renderMisc = DecoRenderMisc::GetSingleton();
	m_renderMisc->RI = _RI;	

//#ifdef MFC_ENABLED
//	string strRotateFileName = CDecoDirectoryManager::GetSingleton()->GetUserDataFolder() + "/models/rotate.xjj";
//	string strAxisXFileName = CDecoDirectoryManager::GetSingleton()->GetUserDataFolder() + "/models/axis_x.xjj";
//	string strAxisYFileName = CDecoDirectoryManager::GetSingleton()->GetUserDataFolder() + "/models/axis_y.xjj";
//	string strAxisZFileName = CDecoDirectoryManager::GetSingleton()->GetUserDataFolder() + "/models/axis_z.xjj";
//	string strPointFileName = CDecoDirectoryManager::GetSingleton()->GetUserDataFolder() + "/models/point.xjj";
//	
//#else
//	string strRotateFileName = "./models/rotate.xjj";
//	string strAxisXFileName = "./models/axis_x.xjj";
//	string strAxisYFileName = "./models/axis_y.xjj";
//	string strAxisZFileName = "./models/axis_z.xjj";
//	string strPointFileName = "./models/point.xjj";
//#endif
//	ifstream in_file;
//	in_file.open( strRotateFileName.c_str(), ios::in | ios::binary );
//	m_renderMisc->m_rotation.ReadFromFile(in_file);
//	in_file.close();
//
//	in_file.open(strAxisXFileName.c_str(), ios::in | ios::binary);
//	m_renderMisc->m_axis_x.ReadFromFile(in_file);
//	in_file.close();
//
//	in_file.open(strAxisYFileName.c_str(), ios::in | ios::binary);
//	m_renderMisc->m_axis_y.ReadFromFile(in_file);
//	in_file.close();
//
//	in_file.open(strAxisZFileName.c_str(), ios::in | ios::binary);
//	m_renderMisc->m_axis_z.ReadFromFile(in_file);
//	in_file.close();
//
//	in_file.open(strPointFileName.c_str(), ios::in | ios::binary);
//	m_renderMisc->m_point.ReadFromFile(in_file);	
//	in_file.close();
}

void DecoRenderMisc::SetLineWidth (FLOAT n)
{
	RI->SetLineWidth(n);
}

void DecoRenderMisc::Serialize(DecoArchive& Ar)
{

}
void DecoRenderMisc::Deserialize(DecoArchive& Ar)
{

}